package org.jeecg.modules.zhongche.plc.service.impl;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.zhongche.plc.api.PlcDataType;
import org.jeecg.modules.zhongche.plc.api.PlcFoot;
import org.jeecg.modules.zhongche.plc.model.PLCWriteDTO;
import org.jeecg.modules.zhongche.plc.runner.PLCRunner;
import org.jeecg.modules.zhongche.plc.service.PlcService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

@Service
@Slf4j
public class PlcServiceImpl implements PlcService {

    @Autowired
    private PLCRunner plcRunner;


    private String getKey(int db) {
        return StrUtil.format("plc-db-{}", db);
    }

    private String getAllLineKey(int db) {
        return StrUtil.format("plc-all-line-db-{}", db);
    }

    /**
     * 写入 桁架站点代码,焊接程序号
     */


//    @Override
//    public void wirteSetp(int dbCode, List<Integer> lineList) {
//
//        for (Integer line : lineList) {
//            RLock lock = redissonLock.getLock(getAllLineKey(dbCode));
//            lock.lock(3, TimeUnit.SECONDS);
//
//            wirteSetp(dbCode, line);
//        }
//    }
    @Override
    public void write(Integer dbCode, String offset, Object value) {
        try {
            Optional.ofNullable(plcRunner)
                    .map(PLCRunner::getDataBlockInfoMap)
                    .map(val -> val.get(dbCode)).ifPresentOrElse(info -> {
                        info.write(offset, value);
                    }, () -> {
                        log.error("写入数据错误,未发现PLC链接");
                    });
        } catch (Exception e) {

            log.error("写入数据错误={}", e.getMessage());
        }
    }

    @Override
    public boolean write(Integer dbCode, String offset, PlcDataType type, Object value) {


        AtomicBoolean result = new AtomicBoolean(false);

        try {

            Optional.ofNullable(plcRunner)
                    .map(PLCRunner::getDataBlockInfoMap)
                    .map(val -> val.get(dbCode)).ifPresentOrElse(info -> {

                        result.set(info.write(offset, type, value));

                    }, () -> {
                        log.error("写入数据错误,未发现PLC链接");
                        throw new RuntimeException(StrUtil.format("写入数据错误,未发现PLC链接={}", dbCode));
                    });
        } catch (Exception e) {

            log.error("写入数据错误={}", e.getMessage());
            throw new RuntimeException(StrUtil.format("写入数据错误={}", e.getMessage()));
        }
        return result.get();
    }

    @Override
    public boolean writeClass(PLCWriteDTO bean) {

        Boolean result = false;

        try {

            PlcFoot foot = Optional.ofNullable(plcRunner)
                    .map(PLCRunner::getDataBlockInfoMap)
                    .map(val -> val.get(bean.getDbNum())).orElse(null);

            if (Objects.isNull(foot)) {
                return false;
            }

            boolean b = foot.writeClass(bean);
            System.out.println("b = " + b);
            return b;
        } catch (Exception e) {

            log.error("写入数据错误={}", e.getMessage());
            throw new RuntimeException(StrUtil.format("写入数据错误={}", e.getMessage()));
        }
    }
//
//    @SneakyThrows
//    public void wirteSetp(int dbCode, int line) {
//
//
//        if (Optional.ofNullable(plcRunner)
//                .map(PLCRunner::getDataBlockInfoMap)
//                .map(val -> val.get(dbCode)).isEmpty()) {
//            return;
//        }
//
//        DataBlockInfo info = plcRunner.getDataBlockInfoMap().get(dbCode);
//
//        {
//            PLCWriteDTO writeDTO = new PLCWriteDTO();
//            writeDTO.setDb150((short) dbCode);
//            writeDTO.setDb154((short) line);
//            info.store(writeDTO);
//        }
//
//        TimeUnit.SECONDS.sleep(1);
//        {
//            PLCWriteDTO writeDTO = new PLCWriteDTO();
//            writeDTO.setDb190(true);
//            info.store(writeDTO);
//        }
//        // 监听是否写入成功
//        RLock lock = redissonLock.getLock(getKey(dbCode));
//        lock.lock(3, TimeUnit.SECONDS);
//        // 然后写入
//
//        {
//            PLCWriteDTO writeDTO = new PLCWriteDTO();
//            writeDTO.setDb190_1(true);
//            info.store(writeDTO);
//        }
//    }


}
